package com.zxt.mq.mvc.log.send;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zxt.mq.config.rabbitmq.RabbitData;
import com.zxt.mq.mvc.log.receive.MessageReceiveLogService;
import com.zxt.mq.mvc.log.send.zconstant.SendLogConstant;
import com.zxt.mq.mvc.log.send.zdomain.MessageSendLog;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;

import javax.annotation.Resource;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;

/**
 * <p>
 * 消息记录 服务实现类
 * </p>
 *
 * @author zxt
 * @since 2022-07-25
 */
@Service
public class MessageSendLogServiceImpl extends ServiceImpl<MessageSendLogMapper, MessageSendLog> implements MessageSendLogService {
    @Value("${spring.rabbitmq.message-log.log}")
    private boolean                  log;
    @Resource
    private MessageReceiveLogService messageReceiveLogService;

    @Override
    public void saveLog(RabbitData rabbitData, String exchangeName, String routerKey) {
        if (log) {
            int sendTime = 0;
            if (ObjectUtil.isNotNull(rabbitData)) {
                MessageSendLog messageLog = getByUri(rabbitData.getUri());
                if (ObjectUtil.isNull(messageLog)) {
                    messageLog = new MessageSendLog();
                } else {
                    sendTime = messageLog.getSendTimes();
                }
                messageLog.setSendMsg(rabbitData.getSendMsg())
                          .setSendTime(LocalDateTime.now())
                          .setStatus(SendLogConstant.SEND_SUCCESS)
                          .setExchangeName(exchangeName)
                          .setRouterKey(routerKey)
                          .setUri(rabbitData.getUri())
                          .setMaxSend(rabbitData.getMaxSend())
                          .setSendTimes(sendTime + 1)
                          .setAlreadyDead("0")
                          .setReqUri(rabbitData.getReqUri())
                          .setIntervalTime(rabbitData.getIntervalTime());
                saveOrUpdate(messageLog);
            }
        }
    }

    @Override
    public void updateLog(String uri, String status, String failReason) {
        if (log) {
            MessageSendLog messageLog = getByUri(uri);
            if (ObjectUtil.isNotNull(messageLog)) {
                if (SendLogConstant.SEND_FAIL.equals(status)) {
                    messageLog.setFailReason(failReason);
                }
                messageLog.setStatus(status);
                updateById(messageLog);
            }
        }
    }

    @Override
    public MessageSendLog getByUri(String uri) {
        if (StrUtil.isEmpty(uri)) {
            return null;
        }
        return getOne(new QueryWrapper<MessageSendLog>().eq(MessageSendLog.DbKey.uri, uri));
    }

    @Override
    public void setMessageToAlreadyDead(MessageSendLog messageSendLog) {
        messageSendLog.setAlreadyDead("1");
        updateById(messageSendLog);
    }

    @Override
    public List<MessageSendLog> listFail() {
        List<MessageSendLog> sendFailList = list(new QueryWrapper<MessageSendLog>().eq(MessageSendLog.DbKey.status,
                                                                                       SendLogConstant.SEND_FAIL)
                                                                                   .ne(MessageSendLog.DbKey.alreadyDead,
                                                                                       "1"));
        List<String> unConfirmList = messageReceiveLogService.listFailUri();
        if (CollUtil.isNotEmpty(unConfirmList)) {
            List<MessageSendLog> unConfirm = list(new QueryWrapper<MessageSendLog>().in(MessageSendLog.DbKey.uri,
                                                                                        unConfirmList)
                                                                                    .ne(MessageSendLog.DbKey.alreadyDead,
                                                                                        "1"));
            if (CollUtil.isNotEmpty(unConfirm)) {
                sendFailList.addAll(unConfirm);
            }
        }

        return sendFailList;
    }
}
